home *** CD-ROM | disk | FTP | other *** search
- // EOController.h
- // Enterprise Objects Framework
- // Copyright (c)1993, NeXT Computer, Inc. All rights reserved.
-
-
- #ifdef SHLIB
- #import "shlib.h"
- #endif
-
- #import <foundation/NSDictionary.h>
- #import <eoaccess/eoaccess.h>
-
- @class EOAssociation;
-
-
- // EOController uses EOAssociations to direct the movement of data between the
- // user interface and a source of data-bearing objects, ensuring that what
- // appears on screen is consistent with data in the objects.
-
-
- @interface EOController : NSObject
- {
- @private
- NSMutableArray *associations;
- NSMutableArray *saveStack;
- NSMutableArray *dataSourceStack;
- NSMutableArray *undoStack;
- NSMutableArray *undoMarkers;
- id <EODataSources> dataSource;
- NSMutableArray *objectArray;
- id delegate;
- id nextController;
- NSMutableArray *selection;
- struct {
- int savesToObjectsAutomatically:1;
- int savesToDataSourceAutomatically:1;
- int marksEveryOperation:1;
- int isUndoEnabled:1;
- int selectsFirstObjectAfterFetch:1;
- int associationNotification:16;
- int _reserved:12;
- } flags;
- id undoScope;
-
- // Used for debugging.
- NSArray *_sortOrdering;
- void *_extras; // id _saveStackText;
- void *_reserved;
-
- unsigned int maximumUndoMarks;
- NSMutableArray *_failureStack;
- }
-
- - initWithDataSource:(id <EODataSources>)dataSource;
- // Initializes a newly allocated EOController to get its data from objects
- // provided by dataSource.
-
- - (void)setDelegate:aDelegate;
- - delegate;
- // These methods set/return the controller's delegate.
-
- - (NSArray *)keys;
- // Returns an array containing the keys used by all the associations for
- // this controller.
-
- - setNextController:(EOController *)aController;
- - (EOController *)nextController;
- // These methods are used for chaining controllers together. Chained
- // controllers propagate fetch, saveToObjects, saveToDataSource, and
- // redisplay.
-
- - (void)addAssociation:(EOAssociation *)anAssociation;
- // Adds anAssociation to the set managed by the controller.
-
- - (void)removeAssociation:(EOAssociation *)anAssociation;
- // Removes anAssociation from the set managed by the controller.
-
- - (NSArray *)associations;
- // Returns the controller's associations.
-
- - (void)disableAssociationNotification;
- - (void)reenableAssociationNotification;
- // Enable or disable sending of EOAssociationNotification messages.
- // Messages are sent by default. These messages nest (one reenable
- // must be sent for every disable).
-
- - (BOOL)isDiscardAllowed;
- // If there are any edits that haven't been saved to the objects sends
- // -controllerWillDiscardEdits: to the delegate. If the delegate doesn't
- // implement this method the controller opens an alert panel asking the
- // user if it's okay to discard edits. Then if there are any operations
- // not flushed to the data source the controller sends
- // -controllerWillDiscardUpdates: to the delegate. Again, if the delegate
- // doesn't implement this method the controller opens an alert panel
- // asking the user to confirm.
-
- - (NSArray *)selectionIndexes;
- // Returns the selection as an array of NSNumbers.
-
- - (BOOL)setSelectionIndexes:(NSArray *)selection;
- // Sets the selection as an array of NSNumbers. The controller sends
- // -isDiscardAllowed to all its detail controllers, as a change in
- // selection will cause detail controllers to change their data source.
- // If any controller returns NO the selection is NOT changed and NO is
- // returned. If an association attempts to change the selection and
- // fails, the association should reset its selection by asking the
- // controller for the current selection. Returns YES on success, NO on
- // failure.
-
- - (BOOL)selectNext;
- // This convenience method increments the selection. If incrementing
- // the selection would set the selection beyond the end of the array
- // then the selection is set to 0. If the previous selection was a
- // multiple selection then the selection is set to the next record
- // after the first item in the previous selection. This method (and
- // it's cover selectNext:) are useful for user interfaces that don't
- // have widgets to directly control the selection. Does not redisplay.
-
- - (BOOL)selectPrevious;
- // This convenience method decrements the selection. If decrementing
- // the selection would set the selection before the start of the array
- // then the selection is set to the last object. If the previous
- // selection was a multiple selection then the selection is set to the
- // previous record before the first item in the previous selection.
- // This method (and it's cover selectPrevious:) are useful for user
- // interfaces that don't have widgets to directly control the selection.
- // Does not redisplay.
-
- - (BOOL)clearSelection;
- // Clears the selection. Shortcut for sending -setSelection: with an
- // empty array. Doesn't redisplay.
-
- - (NSArray *)allObjects;
- // Returns all data-bearing objects accessible through the controller.
-
- - (NSArray *)selectedObjects;
- // Returns the selected objects.
-
- - (id <EODataSources>)dataSource;
- // Returns the data source.
-
- - (void)setDataSource: (id <EODataSources>)dataSource;
- // Sets the new data source.
-
- - (void)redisplay;
- // Sends -contentsDidChange to all the associations.
-
- - (BOOL)fetch;
- // Sends -endEditing to the associations. Then, if there are edits that
- // haven't been sent to the objects, sends -controllerWillDiscardEdits:
- // to the delegate. Then, if there are modifications that haven't been
- // sent to the data source, sends -controllerWillDiscardUpdates: to the
- // delegate. If the delegate agrees, sends -controllerWillFetch: to the
- // delegate. If the delegate agrees, sends -contentsWillChange to all
- // associations, then after fetching, sends -contentsDidChange to all the
- // associations and -controllerDidFetch: to the delegate. Returns YES on
- // success, NO on failure.
-
- - (BOOL)deleteObjectAtIndex:(unsigned)anIndex;
- // Sends -controller:willDeleteObject: to the delegate. If the delegate
- // agrees, deletes the object, then sends -controller:didDeleteObject: to
- // the delegate. If the selection can change -selectionDidChange is sent
- // to the associations. Finally -contentsDidChange is always sent to the
- // associations. Returns YES on success, NO on failure.
-
- - (BOOL)deleteSelection;
- // Iterates over the selection, sending -deleteObjectAtIndex: to self for
- // each object in the selection. Aborts the delete and return NO if
- // any -deleteObjectAtIndex: message returns NO. Returns YES if all
- // objects are successfully deleted.
-
- - insertObjectAtIndex:(unsigned)anIndex;
- // Asks the data source to create a new object using the createObject
- // method. The calls insertObject:atIndex:.
-
- - insertObject: newObject atIndex:(unsigned)anIndex;
- // The newObject should be of an appropriate class for the controller's
- // data source. A new object can be allocated using the data source's
- // createObject method.
- // Sends -controller:willInsertObject:atIndex to the delegate.
- // If the delegate disagrees, the new object is released, otherwise
- // the object is inserted. Returns the object that was inserted, or nil
- // on failure.
-
- - (void)setValues: (NSDictionary *)newValues forObject: anObject;
- // The dictionary newValues should contain key/value pairs that
- // anObject can receive via the EOKeyValueCoding methods. The
- // controller acts as though the values had been received from an
- // association. So, for example, if savesToObjectsAutomatically is
- // not enabled the values will not be sent to the EO.
-
- - (void)associationDidEdit:(EOAssociation *)association;
- // Informs the controller that association has a pending edit. An
- // association must send this message to its controller whenever it ends
- // an editing session.
-
- - (void)endEditing;
- // This method is invoked whenever the controller needs to force an end
- // to text editing. It's invoked from -saveToObjects.
-
- - (BOOL)hasChangesForObjects;
- // Returns YES if any edits need to be made; that is, if any objects
- // have been edited in the user interface but not applied to the objects.
-
- - (BOOL)hasChangesForDataSource;
- // Returns YES if any object has been modified; that is, if any objects
- // have been edited, inserted, or deleted.
-
- - (void)discardEdits;
- // This clears the stack of changes to be made to the data-bearing
- // objects. This method is only useful if -savesToObjectsAutomatically is
- // turned off. This method sends -discardEdits to all the
- // associations.
-
- - (BOOL)saveToObjects;
- // Sends buffered edits to the data-bearing objects via the
- // EOKeyValueCoding category. Buffering is enabled with
- // -setSavesToObjectsAutomatically:. When enabled, edits are buffered
- // whenever an association sends an -associationDidEdit: message to the
- // controller. If the selection changes then any outstanding edits for
- // the previously selected objects are cached.
-
- - (void)setSelectsFirstObjectAfterFetch:(BOOL)yn;
- - (BOOL)selectsFirstObjectAfterFetch;
- // Set/return the selection policy after fetching. If YES and nothing
- // was selected before the fetch then the first object will be selected.
- // If YES and there was a previous selection the controller will attempt
- // to maintain that selection after the fetch. If NO the controller will
- // not alter the selection. The default is YES.
-
- - (BOOL)setSavesToObjectsAutomatically:(BOOL)yn;
- // Fails if there are any buffered edits.
- - (BOOL)savesToObjectsAutomatically;
- // Set/return the automatic object updating policy. If YES edits are sent
- // directly to the selected object (or the first selected object) when an
- // association send a -associationDidEdit: message to the controller. If
- // NO all edits are buffered until an update message is sent to the
- // controller. The default is NO.
-
- - (void)discardOperations;
- // Clears the list of pending operations that would be processed
- // by saveToDataSource.
-
- - (BOOL)saveToDataSource;
- // For each edited, inserted, or deleted object, sends
- // -prepareForDataSource to the object, -controllerWillUpateDataSource:
- // to the delegate, -updateObject:, -insertObject:, or -deleteObject: to
- // the data source, and finally -controllerDidUpateDataSource: to the
- // delegate. If any of these fails, this method fails and returns NO, and
- // no further operations are performed. After successfully saving edits
- // for all of its modified objects, sends -saveToDataSource to all of
- // subcontrollers, and then to the next controller, and returns YES.
-
- - (BOOL)setSavesToDataSourceAutomatically:(BOOL)yn;
- // Fails and returns NO if there are any buffered operations.
- - (BOOL)savesToDataSourceAutomatically;
- // Set/return the automatic data-source updating policy. If YES
- // operations such as insert, delete, and edit are sent directly to the
- // data source. The default is NO.
-
- - (void)setSortOrdering:(NSArray *)keySortOrderArray;
- // sets an EOKeySortOrder array to be applied to all records upon fetch
- - (NSArray *)sortOrdering;
- - (void)resort;
- // forces a resorting of the object array (and a redisplay)
- @end
-
-
- // These methods provide an undo stack by making copies of the operations
- // performed on the data-bearing objects and reverting to previous versions
- // when requested.
-
- @interface EOController (EOUndoBehavior)
-
- - (void)setUndoEnabled:(BOOL)yn;
- - (BOOL)isUndoEnabled;
- // Enables or disabled undo. The default is NO.
-
- - (void)markUndo;
- // Marks the current state of the objects as an undo point.
-
- - (void)setMarksEveryOperation:(BOOL)yn;
- - (BOOL)marksEveryOperation;
- // If this flag is set then every time an insert, delete, or edit is
- // performed a mark is also placed on the undo stack. The default is NO.
-
- - (void)undo;
- // Reverts to the most recent mark, and redisplays everything.
- // Note that if undo is enabled an entry will be made for every insert,
- // delete, or edit. The controller will perform a saveToObjects before
- // the undo is applied.
-
- - (void)releaseUndos;
- // Clears all undo information. No undo is possible until a new mark is
- // established with -markUndo.
-
- - (BOOL)hasUndos;
- // Returns whether this controller has any entries on its undo stack.
-
- - (void)setMaximumUndoMarks:(unsigned int)max;
- - (unsigned int)maximumUndoMarks;
- // Set/return the maximum number of undo marks that will be recorded.
- // Marks added after the maximum will causes earlier marks to fall off the
- // queue. This method is useful for restricting memory usage. Setting
- // the maximum to zero will allow unlimited undo queueing. The default
- // is zero.
-
- @end
-
-
- // These methods are simple convienience methods to facilitate target/action
- // connections in InterfaceBuilder.
-
- @interface EOController (EOControllerTargetAction)
-
- - selectNext: sender;
- // This is a target-action cover for -selectNext. Also sends
- // -redisplay after changing the selection.
-
- - selectPrevious: sender;
- // This is a target-action cover for -selectPrevious. Also sends
- // -redisplay after changing the selection.
-
- - fetch:sender;
- // This is a target-action cover for -fetch.
-
- - insert:sender;
- // Inserts an object after the selected object, or, if nothing is
- // selected, at the end of the array.
-
- - delete:sender;
- // This is a target-action cover for -deleteObjectAtIndex:. Deletes the
- // first selected object, or, if nothing is selected the last object.
-
- - saveToObjects:sender;
- - markUndo:sender;
- - undo:sender;
- - saveToDataSource:sender;
- - discardOperations:sender;
- - discardEdits:sender;
- // These are target-action covers for the methods of the same name with
- // no arguments.
-
- @end
-
-
- // This optional protocol describes the methods a delegate of the
- // EOController may implement.
-
- @interface NSObject (EOControllerDelegate)
-
- - (void)controllerDidChangeSelection:(EOController *)controller;
- // Sent when the selection changes.
-
- - (BOOL)controllerWillFetch:(EOController *)controller;
- // Informs the delegate that the controller is about to fetch. If the
- // delegate returns no the fetch fails; if the delegate returns YES
- // the fetch proceeds.
-
- - (void)controller:(EOController *)controller didFetchObjects: (NSArray *)objects;
- // Informs the delegate that the controller has fetched object.
-
- - (void)controller:(EOController *)controller sortObjects:(NSMutableArray *)objects;
- // If the delegate implements this method, it is responsible for sorting
- // the given object array. If the delegate does not implement this method
- // and a sortOrdering has been specified, the controller will sort the objects
- // itself using [objects sortUsingKeyOrderArray:[self sortOrdering]];
-
- // Note that the insert, delete, and update operations are buffered until an
- // -saveToDataSource message is sent to the controller. The delegate receives
- // delegate messages for these operations as the insert, delete, and update
- // operations are sent to the controller. The delegate receives different
- // delegate messages when the buffered operations are actually sent on to the
- // data source.
-
- - (BOOL)controller:(EOController *)controller willInsertObject:object atIndex: (unsigned)newIndex;
- // If the delegate returns NO object is released and not inserted.
-
- - (void)controller:(EOController *)controller didInsertObject:object;
- // Informs the delegate that the controller has inserted object.
-
-
- - (BOOL)controller:(EOController *)controller willDeleteObject:object;
- // If the delegate returns NO object is not deleted.
-
- - (void)controller:(EOController *)controller didDeleteObject:object;
- // Informs the delegate that the controller has deleted object.
-
- - (NSDictionary *)controller:(EOController *)controller willSaveEdits: (NSDictionary *)edits toObject:object;
- // Invoked by -saveObjects for each object before
- // -takeValuesFromDictionary: is sent to the object. If the delegate
- // responds nil -takeValuesFromDictionary: is not sent and the controller
- // aborts -saveToObjects. The edits will be ignored and the associations
- // will not be notified of any change. If the delegate returns a
- // dictionary that dictionary will be sent to the object. This method is
- // useful for doing validation prior to data actually being sent to the
- // object and will also prevent the UI from refreshing.
-
- - (void)controller:(EOController *)controller didSaveToObject:object;
- // Informs the delegate that the controller has saved object.
-
- - (BOOL)controllerWillDiscardEdits:(EOController *)controller;
- // Sent during the -fetch method before the fetch begins if there are any
- // operations that haven't been saved to the objects. Also sent when a
- // selection is about to change, causing a detail controller to flush its
- // caches. The operation is aborted if this method returns NO. The
- // delegate should send -saveToObjects if it wants to preserve the
- // changes. If the delegate doesn't implement this method the controller
- // opens an alert panel warning the user that edits may be lost.
-
- - (BOOL)controllerWillDiscardOperations:(EOController *)controller;
- // Sent during the -fetch method before the fetch begins if there are any
- // operations that haven't been saved to the data source. Also sent
- // when a selection is about to change, causing a detail controller to
- // flush its caches. The fetch is aborted if this method returns NO.
- // The delegate should invoke -saveToDataSource if it wants to preserve the
- // changes. If the delegate doesn't implement this method the controller
- // opens an alert panel warning the user that updates may be lost.
-
-
- - (BOOL)controllerWillSaveToDataSource:(EOController *)controller;
- - (void)controllerDidSaveToDataSource:(EOController *)controller;
- // These delegate messages are sent as the data source is notified of
- // changes to data-bearing objects. If the savesToDataSourceAutomatically
- // flag is turned off and -saveToDataSource is invoked then the delegate
- // is notified of each buffered operation.
-
-
- typedef enum {
- EONoDataSourceFailure = 0,
- EOContinueDataSourceFailureResponse,
- EORollbackDataSourceFailureResponse
- } EODataSourceFailureResponse;
- // These return values allow a controller's delegate to determine what
- // action should be taken on a failure. EONoDataSourceFailure means there
- // was no failure; EOContinuteDataSourceFailureResponse means that the
- // failure should be ignored and the operation should continue;
- // EORollbackDataSourceFailureResponse means that the controller should
- // roll back the data source. EORollbackDataSourceFailureResponse is only
- // useful if the data source conforms to the EORollbackDataSource
- // protocol.
-
- typedef enum {
- EODiscardDataSourceOperation = 0, // NO response in EOF 1.0
- EOPerformDataSourceOperation, // YES response in EOF 1.0
- EOContinueDataSourceOperation,
- EORollbackDataSourceOperation,
- } EODataSourceOperationDelegateResponse;
- // The return values allow a controller's delegate to dictate
- // in a will<Operation>inDataSource method what should be done
- // with the current operation. EOPerformDataSourceOperation means
- // the operation should proceed. EODiscardDataSourceOperation means
- // the operation should not be performed, and should be discarded
- // from the operation stack. EOContinueDataSourceOperation means
- // that the operation not be performed but should be left on the
- // operation stack to be performed on the next save. EORollbackDataSourceOperation
- // indicates that the current saveToDataSource operation should be
- // aborted and all changes rolled back.
-
- // These methods are currently undocumented.
-
- - (EODataSourceFailureResponse)controller:(EOController *)controller
- object:object
- failedToPrepareForDataSource:dataSource;
-
- - (EODataSourceOperationDelegateResponse)controller:(EOController *)controller
- willInsertObject:object
- inDataSource:dataSource;
-
- - (EODataSourceFailureResponse)controller:(EOController *)controller
- failedToInsertObject:object
- inDataSource:dataSource;
-
- - (void)controller:(EOController *)controller
- didInsertObject:object
- inDataSource:dataSource;
-
- - (EODataSourceOperationDelegateResponse)controller:(EOController *)controller
- willDeleteObject:object
- inDataSource:dataSource;
-
- - (EODataSourceFailureResponse)controller:(EOController *)controller
- failedToDeleteObject:object
- inDataSource:dataSource;
-
- - (void)controller:(EOController *)controller
- didDeleteObject:object
- inDataSource:dataSource;
-
- - (EODataSourceOperationDelegateResponse)controller:(EOController *)controller
- willUpdateObject:object
- inDataSource:dataSource;
-
- - (EODataSourceFailureResponse)
- controller:(EOController *)controller
- failedToUpdateObject:object
- inDataSource:dataSource;
-
- - (void)controller:(EOController *)controller
- didUpdateObject:object
- inDataSource:dataSource;
-
- - (void) controller:(EOController *)controller
- saveObjectsFailedForDataSource:dataSource;
-
- - (void) controller:(EOController *)controller
- createObjectFailedForDataSource:dataSource;
-
- - (void)controller:(EOController *)controller willRollbackDataSource:(id <EODataSources>)dataSource;
- - (void)controller:(EOController *)controller didRollbackDataSource:(id <EODataSources>)dataSource;
-
-
- - (BOOL)controllerWillUndo:(EOController *)controller;
- - (void)controllerDidUndo:(EOController *)controller;
-
- - (void)controller:(EOController *)controller didChangeDataSource: (id <EODataSources>)dataSource;
-
- - (void)controller:(EOController *)controller association: (EOAssociation *)association didEditObject: anObject key: (NSString *)key value: aValue;
-
- - (BOOL)controller:(EOController *)controller willUndoObject:anObject;
- - (void)controller:(EOController *)controller didUndoObject:anObject;
-
- @end
-
-
- @protocol EOObjectValidation
-
- - (BOOL)prepareForDataSource;
- // Sent to objects before they are updated in, inserted into, or deleted
- // from the data source. If the object returns NO the data source
- // operation will not be performed.
-
- @end
-
-
- // These notifications are sent by EOController to EOAssociations.
-
- @protocol EOAssociationNotification
-
- - (void)contentsDidChange;
- // Sent to all associations whenever data may have changed; for example,
- // when a controller's data source is changed. Associations should only
- // update themselves if the value is in fact different from what they're
- // currently displaying.
-
- - (void)selectionDidChange;
- // Sent to all associations whenever selection has changed.
-
- - (void)endEditing;
- // Sent when the receiver should end editing. This is a necessary to
- // correctly disassociate the window's field editor for the widget's view.
-
- - (void)discardEdits;
- // The association should discard any buffer edits. This is sent by the
- // controller before objects are fetched from the data source.
-
- @end
-